package com.gopay.bis.service.bank.impl.expay;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.bis.dao.bankorder.BankContractInfoDAO;
import com.gopay.bis.manager.bank.NuccSerialManager;
import com.gopay.bis.manager.bank.expay.NuccExPayManager;
import com.gopay.bis.manager.bank.payconfig.BisBankExtConfigManager;
import com.gopay.bis.service.bank.sms.SmsSupportController;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.*;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.core.dic.dao.DicBankRetCodeQueryDAO;
import com.gopay.common.domain.bank.ExPayBaseMessage;
import com.gopay.common.domain.bank.nucc.expay.NuccExpayBaseMessage;
import com.gopay.common.domain.bank.nucc.expay.cert.res.NuccExpayCertRes;
import com.gopay.common.domain.bank.nucc.expay.pay.end.NuccExpaymentEndRes;
import com.gopay.common.domain.bank.nucc.expay.pay.res.NuccExpaymentRes;
import com.gopay.common.domain.bank.nucc.expay.query.res.NuccExpayQueryRes;
import com.gopay.common.domain.bank.nucc.expay.refund.end.NuccExpayRefundEndRes;
import com.gopay.common.domain.bank.nucc.expay.refund.res.NuccExpayRefundRes;
import com.gopay.common.domain.bank.nucc.expay.rescind.res.NuccExpayRescindBodySgninf;
import com.gopay.common.domain.bank.nucc.expay.rescind.res.NuccExpayRescindRes;
import com.gopay.common.domain.bis.BisBankContractInfo;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.MD5Util;
import com.gopay.remote.bank.ExPayInteractRemoteService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import java.util.HashMap;
import java.util.Map;

/**
 * 网联快捷实现类
 * 
 * @ClassName: NuccExPayServiceImpl
 * @author w_jiqing
 * @date 2017年7月12日 上午10:06:45
 */
@Service("nuccExPayService")
public class NuccExPayServiceImpl implements ExPayInteractRemoteService {
    

    private static Logger logger = LoggerFactory.getLogger(NuccExPayServiceImpl.class);
    
    @Resource(name = "nuccUrlConfig")
    private Map<String, String> nuccUrlConfig;

    @Resource(name = "nuccExPayManager")
    private NuccExPayManager nuccExPayManager;
    
    @Resource(name = "nuccSerialManager")
	private NuccSerialManager nuccSerialManager;

    @Resource(name = "bankContractInfoDAO")
    private BankContractInfoDAO bankContractInfoDAO;

    @Resource(name = "bisBankExtConfigManager")
    BisBankExtConfigManager bisBankExtConfigManager;
    
    @Resource(name = "dicBankRetCodeQueryDAO")
    private DicBankRetCodeQueryDAO dicBankRetCodeQueryDAO;

    public SmsSupportController smsController;
    
    @Value("${NUCC.SERIAL.CONTROL}")
    private String nuccSerialControl;

    @Override
    public Result certification(ExPayBaseMessage baseMsg) {
        Result result = new Result();
        result.setSuccess(true);
        result.setModel("flag", true);
        return result;
    }

    /**
     * 解约通知
     * @param baseMsg
     * @return
     */
    @Override
    public Result cancel(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        NuccExpayRescindRes message = new NuccExpayRescindRes();
        BeanUtils.copyProperties(baseMsg, message);
        message.setOutStlmCd(BankConstants.BANK_LOGO_NUCCPAY);
        try {
            message = (NuccExpayRescindRes) nuccExPayManager.cancelVerify(message);
            if (message.isSuccess() && message.getMsgBody().getBizInf().getBizStsCd() != null
                    && NuccConstants.NUCC_BIZSTSCD_SUCCESS
                            .equals(message.getMsgBody().getBizInf().getBizStsCd())) {
                // 网联通知解约--验签成功并且业务成功，更新签约状态
                NuccExpayRescindBodySgninf sgnInf = message.getMsgBody().getSgnInf();
                String sgnNo = sgnInf.getSgnNo();
                String bankCode = BankOfAffiliationConstants.getBankCode(sgnInf.getSgnAcctIssrId());
                BisBankContractInfo bbci = findContractInfoBySgnNo(sgnNo, bankCode, BisBankInterfaceChannel._18.value);
                if (bbci != null && BankContractConstants.CONTRACT_SUCCESS.equals(bbci.getContractState())) {
                    bbci.setContractState(BankContractConstants.CONTRACT_CANCEL);
                    updateContractStateBySingNo(bbci);
                }
                result.setSuccess(true);
            }
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6054);
        }
        return result;
    }

    @Override
    public Result sendSms(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        NuccExpayBaseMessage message = new NuccExpayBaseMessage();
        BeanUtils.copyProperties(baseMsg, message);
        try {
            // 查找该卡签约记录
            BisBankContractInfo contractInfo = findContractInfo(message);
            Map<String, String> smsRes = smsController.querySendSMS(message);
            if (contractInfo == null) {                
                logger.error("本地无网联签约记录，需发起认证申请,gopayOrderId:"+message.getOrderId());
                // 调用网联
                if ("00".equals(smsRes.get("flag"))) {
                    NuccExpayCertRes res = (NuccExpayCertRes) nuccExPayManager.sendSms(message);
                    if (res != null && res.getMsgBody()!=null && res.getMsgBody().getBizInf() !=null
                    		&& res.getMsgBody().getBizInf().getBizStsCd() != null
                            && NuccConstants.NUCC_BIZSTSCD_SUCCESS.equals(res.getMsgBody().getBizInf().getBizStsCd())) {
                        // 银行发送短信成功
                        smsRes = smsController.buildSendLog(message, Integer.valueOf(smsRes.get("sendCount")));
                        result.setModel("flag", true);
                    } else {
                        // 如果流水号异常，调用流水号任务
                        if (res != null&&res.getMsgBody()!=null &&res.getMsgBody().getSysRtnInf()!=null
                        		&& res.getMsgBody().getSysRtnInf().getSysRtnCd() != null
                                && (NuccConstants.NUCC_SYSRTNCD_SERIAL_ERROR.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd()))) {
                        	nuccSerialManager.getFlowIdRule();
                        }
                        // 各种失败（发送短信失败）
                        result.setModel("flag", false);
                        smsRes.put("resCode", ProcCodeConstants.PROC_CODE_100E6096);
                        smsRes.put("sendCount", Integer.valueOf(smsRes.get("sendCount")) + 1 + "");
                        smsRes.put("retMsg", "获取短信验证码失败，请稍后再试");
                    }
                    result.setModel("sendCount", smsRes.get("sendCount"));
                    result.setModel("retMsg", smsRes.get("retMsg"));
                    result.setModel("resCode", smsRes.get("resCode"));
                    result.setResultCode(smsRes.get("resCode"));
                } else {
                    // 不允许发送短信
                    result.setModel("flag", false);
                    result.setModel("retMsg", smsRes.get("retMsg"));
                    result.setModel("resCode", smsRes.get("resCode"));
                    result.setResultCode(smsRes.get("resCode"));
                }
            } else if (BankContractConstants.CONTRACT_SUCCESS.equals(contractInfo.getContractState())) {
                 logger.error("本地存在有效的网联签约记录,gopayOrderId:"+message.getOrderId());
                // 签约有效
                String verifyCode = createVerificationCode(message); 
                if (StringUtils.equals(verifyCode, contractInfo.getVerificationCode())) {
                    logger.error("本地存在网联签约记录，对比一致，调用国付宝短信网关.");
                    Map<String, String> sendRes = smsController.sendSMS(message);
                    // 对比四要素一致，国付宝发送验证码
                    if (ProcCodeConstants.PROC_CODE_100E6102.equals(sendRes.get("resCode"))) {
                        // 短信发送成功
                        result.setModel("flag", true);
                    } else {
                        // 短信发送失败
                        result.setModel("flag", false);
                    }
                    result.setModel("sendCount", sendRes.get("sendCount"));
                    result.setModel("retMsg", sendRes.get("retMsg"));
                    result.setModel("resCode", sendRes.get("resCode"));
                    result.setResultCode(sendRes.get("resCode"));
                } else {
                    // 对比不一致，调用网联
                    if ("00".equals(smsRes.get("flag"))) {
                        logger.error("本地存在网联签约记录，对比不一致，发起解约申请，gopayOrderId:"+message.getOrderId());
                        NuccExpayRescindRes rescindRes = (NuccExpayRescindRes) nuccExPayManager.rescind(message,contractInfo.getContractNumber());
                        if (rescindRes != null&& rescindRes.getMsgBody()!=null&&rescindRes.getMsgBody().getBizInf()!=null && rescindRes.getMsgBody().getBizInf().getBizStsCd() != null
                                && NuccConstants.NUCC_BIZSTSCD_SUCCESS.equals(rescindRes.getMsgBody().getBizInf().getBizStsCd())) {
                            // 更改签约状态
                            updateContractStatus(baseMsg, BankContractConstants.CONTRACT_CANCEL);
                            logger.error("解约成功，已更改签约状态为02，签约失效，重新起认证申请，gopayOrderId:"+message.getOrderId());
                            NuccExpayCertRes res = (NuccExpayCertRes) nuccExPayManager.sendSms(message);
                            if (res != null&&res.getMsgBody()!=null&&res.getMsgBody().getSysRtnInf()!=null
                            		&& res.getMsgBody().getSysRtnInf().getSysRtnCd() != null
                                    && NuccConstants.NUCC_BIZSTSCD_SUCCESS.equals(res.getMsgBody().getBizInf().getBizStsCd())) {
                                // 银行发送短信成功
                                smsRes = smsController.buildSendLog(message,Integer.valueOf(smsRes.get("sendCount")));
                                result.setModel("flag", true);
                            } else {
                                // 如果流水号异常，调用流水号任务
                                if (res != null &&res.getMsgBody()!=null&&res.getMsgBody().getSysRtnInf()!=null
                                		&& res.getMsgBody().getSysRtnInf().getSysRtnCd() != null
                                        && (NuccConstants.NUCC_SYSRTNCD_SERIAL_ERROR.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd()))) {
                                	nuccSerialManager.getFlowIdRule();
                                }
                                // 各种失败（发送短信失败）
                                result.setModel("flag", false);
                                smsRes.put("resCode", ProcCodeConstants.PROC_CODE_100E6096);
                                smsRes.put("sendCount", Integer.valueOf(smsRes.get("sendCount")) + 1 + "");
                                smsRes.put("retMsg", "获取短信验证码失败，请稍后再试");
                            }
                            result.setModel("sendCount", smsRes.get("sendCount"));
                            result.setModel("retMsg", smsRes.get("retMsg"));
                            result.setModel("resCode", smsRes.get("resCode"));
                            result.setResultCode(smsRes.get("resCode"));
                        } else {
                            // 解约失败，即发送验证码失败
                            result.setModel("flag", false);
                            smsRes.put("resCode", ProcCodeConstants.PROC_CODE_100E6096);
                            smsRes.put("sendCount", Integer.valueOf(smsRes.get("sendCount")) + 1 + "");
                            smsRes.put("retMsg", "获取短信验证码失败，请稍后再试");
                            result.setModel("sendCount", smsRes.get("sendCount"));
                            result.setModel("retMsg", smsRes.get("retMsg"));
                            result.setModel("resCode", smsRes.get("resCode"));
                            result.setResultCode(smsRes.get("resCode"));
                        }
                    } else {
                        // 不允许发送短信
                        result.setModel("flag", false);
                        result.setModel("retMsg", smsRes.get("retMsg"));
                        result.setModel("resCode", smsRes.get("resCode"));
                        result.setResultCode(smsRes.get("resCode"));
                    }
                }
            } else {
                // 签约无效
                if ("00".equals(smsRes.get("flag"))) {
                    logger.error("本地网联签约记录，已失效，发起网联认证申请，gopayOrderId:"+message.getOrderId());
                    NuccExpayCertRes res = (NuccExpayCertRes) nuccExPayManager.sendSms(message);
                    if (res != null && res.getMsgBody().getSysRtnInf().getSysRtnCd() != null
                            && NuccConstants.NUCC_BIZSTSCD_SUCCESS.equals(res.getMsgBody().getBizInf().getBizStsCd())) {
                        // 银行发送短信成功
                        smsRes = smsController.buildSendLog(message, Integer.valueOf(smsRes.get("sendCount")));
                        result.setModel("flag", true);
                    } else {
                         // 如果流水号异常，调用流水号任务
                        if (res != null&&res.getMsgBody()!=null&&res.getMsgBody().getSysRtnInf()!=null && res.getMsgBody().getSysRtnInf().getSysRtnCd() != null
                                && (NuccConstants.NUCC_SYSRTNCD_SERIAL_ERROR.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd()))) {
                        	nuccSerialManager.getFlowIdRule();
                        }
                        // 各种失败（发送短信失败）
                        result.setModel("flag", false);
                        smsRes.put("resCode", ProcCodeConstants.PROC_CODE_100E6096);
                        smsRes.put("sendCount", Integer.valueOf(smsRes.get("sendCount")) + 1 + "");
                        smsRes.put("retMsg", "获取短信验证码失败，请稍后再试");
                    }
                    result.setModel("sendCount", smsRes.get("sendCount"));
                    result.setModel("retMsg", smsRes.get("retMsg"));
                    result.setModel("resCode", smsRes.get("resCode"));
                    result.setResultCode(smsRes.get("resCode"));
                } else {
                    // 不允许发送短信
                    result.setModel("flag", false);
                    result.setModel("retMsg", smsRes.get("retMsg"));
                    result.setModel("resCode", smsRes.get("resCode"));
                    result.setResultCode(smsRes.get("resCode"));
                }
            }
            result.setSuccess(true);
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6077);
        }
        return result;
    }

    @Override
    public Result checkSms(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        NuccExpayBaseMessage message = new NuccExpayBaseMessage();
        BeanUtils.copyProperties(baseMsg, message);
        try {
            // 查找该卡签约记录
            BisBankContractInfo contractInfo = findContractInfo(message);
            if (contractInfo == null) {
                Map<String, String> smsRes = smsController.queryCheckSMS(baseMsg);
                if ("00".equals(smsRes.get("flag"))) {
                    logger.error("本地无网联签约记录，发起签约申请,gopayOrderId:"+message.getOrderId());
                    NuccExpayCertRes res = (NuccExpayCertRes) nuccExPayManager.checkSms(message);
                    if (res != null && res.getMsgBody()!=null &&res.getMsgBody().getSysRtnInf()!=null
                    		&& res.getMsgBody().getSysRtnInf().getSysRtnCd() != null
                            && NuccConstants.NUCC_BIZSTSCD_SUCCESS.equals(res.getMsgBody().getBizInf().getBizStsCd())) {
                        // 校验短信通过(签约成功) 并保存签约记录
                        result.setModel("flag", true);
                        newContract(message, res.getMsgBody().getBizInf().getSgnNo());
                    } else {
                        // 如果流水号异常，调用流水号任务
                        if (res != null&&res.getMsgBody()!=null && res.getMsgBody().getSysRtnInf()!=null
                        		&& res.getMsgBody().getSysRtnInf().getSysRtnCd() != null
                                && (NuccConstants.NUCC_SYSRTNCD_SERIAL_ERROR.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd()))) {
                        	nuccSerialManager.getFlowIdRule();
                        }
                        // 校验失败（包含验签，错误验证码等原因）
                        result.setModel("flag", false);
                        smsRes = smsController.buildCheckLog(message, Integer.valueOf(smsRes.get("failCount")));
                    }
                } else {
                    result.setModel("flag", false);
                }
                if (!(boolean) result.getModel("flag")
                        && !ProcCodeConstants.PROC_CODE_100E6099.equals(smsRes.get("resCode"))) {
                    Map<String, String> freezeRes = smsController.freezeCard(message);
                    if (freezeRes != null){
                        smsRes = freezeRes;
                    }
                }
                result.setModel("failCount", smsRes.get("failCount"));
                result.setModel("retMsg", smsRes.get("retMsg"));
                result.setModel("resCode", smsRes.get("resCode"));
                result.setResultCode(smsRes.get("resCode"));
            } else if (BankContractConstants.CONTRACT_SUCCESS.equals(contractInfo.getContractState())) {
                logger.error("本地存在有效的网联签约记录，调用国付宝短信网关，gopayOrderId:"+message.getOrderId());
                Map<String, String> smsRes = smsController.checkSMS(message);
                if (ProcCodeConstants.PROC_CODE_100E6091.equals(smsRes.get("resCode"))) {
                    // 验证通过
                    result.setModel("flag", true);               
                } else {
                    // 验证失败
                    result.setModel("flag", false);
                    if(!ProcCodeConstants.PROC_CODE_100E6099.equals(smsRes.get("resCode"))){
                        Map<String, String> freezeRes = smsController.freezeCard(message);
                        if(freezeRes != null){
                            smsRes = freezeRes;
                        }
                    }
                }
                result.setModel("failCount", smsRes.get("failCount"));
                result.setModel("retMsg", smsRes.get("retMsg"));
                result.setModel("resCode", smsRes.get("resCode"));
                result.setResultCode(smsRes.get("resCode"));
                result.setSuccess(true);
            } else {
                Map<String, String> smsRes = smsController.queryCheckSMS(baseMsg);
                if ("00".equals(smsRes.get("flag"))) {
                    logger.error("本地存在网联签约记录，已失效，发起网联签约申请，gopayOrderId:"+message.getOrderId());
                    NuccExpayCertRes res = (NuccExpayCertRes) nuccExPayManager.checkSms(message);
                    if (res != null&&res.getMsgBody()!=null &&res.getMsgBody().getSysRtnInf()!=null
                    		&& res.getMsgBody().getSysRtnInf().getSysRtnCd() != null
                            && NuccConstants.NUCC_BIZSTSCD_SUCCESS.equals(res.getMsgBody().getBizInf().getBizStsCd())) {
                        // 校验短信通过(签约成功) 并保存签约记录
                        result.setModel("flag", true);
                        updateContractInfo(baseMsg, res.getMsgBody().getBizInf().getSgnNo());
                    } else {
                        // 如果流水号异常，调用流水号任务
                        if (res != null&&res.getMsgBody()!=null&&res.getMsgBody().getSysRtnInf()!=null
                        		&& res.getMsgBody().getSysRtnInf().getSysRtnCd() != null
                                && (NuccConstants.NUCC_SYSRTNCD_SERIAL_ERROR.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd()))) {
                        	nuccSerialManager.getFlowIdRule();
                        }
                        // 校验失败（包含验签，错误验证码等原因）
                        result.setModel("flag", false);
                        smsRes = smsController.buildCheckLog(message, Integer.valueOf(smsRes.get("failCount")));
                    }
                } else {
                    result.setModel("flag", false);
                }
                if (!(boolean) result.getModel("flag")
                        && !ProcCodeConstants.PROC_CODE_100E6099.equals(smsRes.get("resCode"))) {
                    Map<String, String> freezeRes = smsController.freezeCard(message);
                    if (freezeRes != null){
                        smsRes = freezeRes;
                    }
                }
                result.setModel("failCount", smsRes.get("failCount"));
                result.setModel("retMsg", smsRes.get("retMsg"));
                result.setModel("resCode", smsRes.get("resCode"));
                result.setResultCode(smsRes.get("resCode"));
            }
            result.setSuccess(true);
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6078);
        }
        return result;
    }

    @Override
    public Result payment(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        NuccExpayBaseMessage message = new NuccExpayBaseMessage();
        try {
        	nuccSerialManager.generateFlowIdBySerial(baseMsg,true,nuccSerialControl);
            BeanUtils.copyProperties(baseMsg, message);
            BisBankContractInfo contractInfo = findContractInfo(message);
            if(contractInfo!=null){
            	message.setAgrmtNo(contractInfo.getContractNumber());
            }
            NuccExpaymentRes res = (NuccExpaymentRes) nuccExPayManager.payment(message);
            result.setModel("res", message);
            result.setDefaultModel(res.isSuccess());
            Map<String, String> param = new HashMap<String, String>();
            if (res != null
                    && NuccConstants.NUCC_SYSRTNCD_SUCCESS.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd())
                    && (NuccConstants.NUCC_TRXSTATUSCD_SUCCESS.equals(res.getMsgBody().getBizInf().getTrxStatus())
                            || NuccConstants.NUCC_EXCEPTION_SUCCESS.equals(res.getMsgBody().getBizInf().getTrxStatus()))) {
                // 交易成功
                String amount = res.getMsgBody().getBizInf().getTrxAmt();
                param.put("orderId", message.getOrderId());
                param.put("amt", amount.substring(amount.indexOf("CNY")+3, amount.length()));
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "00");
                param.put("retCode", "00");
                param.put("retMsg", "验签成功");
                param.put("isFront", String.valueOf(false));
                result.setModel("isNotifyCashier", param);
                result.setSuccess(true);
                result.setOrderStatus(true);
                // 退款时需获取该字段
                baseMsg.setBankReturnOrderId(res.getMsgBody().getBizInf().getDbtrBankId());
                //新增交易批次号，方便后续对账
                baseMsg.setTransBatchNo(res.getMsgBody().getBizInf().getBatchId());
            }else if(res != null
                    && NuccConstants.NUCC_SYSRTNCD_SUCCESS.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd())
                    && (NuccConstants.NUCC_TRXSTATUSCD_FAIL.equals(res.getMsgBody().getBizInf().getTrxStatus())
                            || NuccConstants.NUCC_EXCEPTION_FAIL.equals(res.getMsgBody().getBizInf().getTrxStatus()))){
                //交易失败
                String amount = res.getMsgBody().getBizInf().getTrxAmt();
                param.put("orderId", message.getOrderId());
                param.put("amt", amount.substring(amount.indexOf("CNY")+3, amount.length()));
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "01");
                param.put("retCode", "01");
                param.put("signData", "");
                param.put("retMsg", res.getReturnInfo());
                //param.put("retMsg", dicBankRetCodeQueryDAO.translateBankRetCode(BankConstants.BANK_LOGO_NUCCPAY,res.getBankRetCode()));
                param.put("isFront", String.valueOf(false));
                result.setModel("isNotifyCashier", param);
                result.setSuccess(true);
                result.setOrderFail(true);
                result.setOrderStatus(false);
                result.setBankRetCode(res.getBankRetCode());
                baseMsg.setTransBatchNo(res.getMsgBody().getBizInf().getBatchId());
            }else {
                // 如果流水号异常，调用流水号任务
                if (res != null&&res.getMsgBody()!=null&&res.getMsgBody().getSysRtnInf()!=null
                		&& res.getMsgBody().getSysRtnInf().getSysRtnCd() != null
                        && (NuccConstants.NUCC_SYSRTNCD_SERIAL_ERROR.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd()))) {
                	nuccSerialManager.getFlowIdRule();
                }
                if(res!=null){
                	param.put("retMsg", res.getReturnInfo());
                	//param.put("retMsg", dicBankRetCodeQueryDAO.translateBankRetCode(BankConstants.BANK_LOGO_NUCCPAY,res.getBankRetCode()));
                	result.setBankRetCode(res.getBankRetCode());
                }
                // 通知后台地址该订单失败
                param.put("orderId", baseMsg.getOrderId());
                param.put("amt", baseMsg.getAmount().toString());
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "01");
                param.put("retCode", "01");
                param.put("isFront", String.valueOf(false));
                result.setModel("isNotifyCashier", param);
                result.setSuccess(true);
                result.setOrderStatus(false);
            }
        } catch (GopayException e) {
            BankLogUtils.printServiceImplExceptionLog(e);
            result.setResultCode(e.getErrCode());
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6057);
        }
        return result;
    }
    

    @Override
    public Result refund(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        NuccExpayBaseMessage message = new NuccExpayBaseMessage();
        BeanUtils.copyProperties(baseMsg, message);
        try {
            NuccExpayRefundRes res = (NuccExpayRefundRes) nuccExPayManager.refund(message);
            result.setDefaultModel(res.isSuccess());
            Map<String, String> param = new HashMap<String, String>();
            if (res != null
                    && NuccConstants.NUCC_SYSRTNCD_SUCCESS.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd())
                    && (NuccConstants.NUCC_TRXSTATUSCD_SUCCESS.equals(res.getMsgBody().getBizInf().getTrxStatus())
                            || NuccConstants.NUCC_EXCEPTION_SUCCESS.equals(res.getMsgBody().getBizInf().getTrxStatus()))) {
                // 退款成功
                String amount = res.getMsgBody().getBizInf().getTrxAmt();
                param.put("orderId", baseMsg.getOrderId());
                param.put("amt", amount.substring(amount.indexOf("CNY")+3, amount.length()));
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "00");
                param.put("retCode", "00");
                param.put("retMsg", "验签成功");
                param.put("isFront", String.valueOf(false));
                result.setModel("isNotifyCashier", param);
                result.setSuccess(true);
                result.setOrderStatus(true);
                baseMsg.setTransBatchNo(res.getMsgBody().getBizInf().getBatchId());//新增交易批次号
            } else {
             // 如果流水号异常，调用流水号任务
                if (res != null&&res.getMsgBody()!=null&&res.getMsgBody().getSysRtnInf()!=null
                		&& res.getMsgBody().getSysRtnInf().getSysRtnCd() != null
                        && (NuccConstants.NUCC_SYSRTNCD_SERIAL_ERROR.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd()))) {
                	nuccSerialManager.getFlowIdRule();
                }
                param.put("orderId", baseMsg.getOrderId());
                param.put("amt", baseMsg.getAmount().toString());
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "01");
                param.put("retCode", "01");
                param.put("retMsg",
                        NuccConstants.NUCC_SYSRTNCD_SUCCESS.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd())
                                ? res.getMsgBody().getBizInf().getBizStsDesc()
                                : res.getMsgBody().getSysRtnInf().getSysRtnDesc());
                param.put("isFront", String.valueOf(false));
                result.setModel("isNotifyCashier", param);
                result.setSuccess(true);
                result.setOrderStatus(false);
            }
        } catch (GopayException e) {
            BankLogUtils.printServiceImplExceptionLog(e);
            result.setResultCode(e.getErrCode());
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6087);
        }
        return result;
    }

    @Override
    public Result sign(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result refundBack(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        NuccExpayRefundEndRes message = new NuccExpayRefundEndRes();
        BeanUtils.copyProperties(baseMsg, message);
        try {
            message = (NuccExpayRefundEndRes) nuccExPayManager.refundVerify(message);
            result.setModel("res", message);
            result.setDefaultModel(message.isSuccess());
            Map<String, String> param = new HashMap<String, String>();
            if (message.isSuccess()
                    && NuccConstants.NUCC_SYSRTNCD_SUCCESS.equals(message.getMsgBody().getSysRtnInf().getSysRtnCd())
                    && (NuccConstants.NUCC_TRXSTATUSCD_SUCCESS.equals(message.getMsgBody().getBizInf().getTrxStatus())
                            || NuccConstants.NUCC_EXCEPTION_SUCCESS.equals(message.getMsgBody().getBizInf().getTrxStatus()))) {
                // 退款成功
                String amount = message.getMsgBody().getTrxInf().getTrxAmt();
                param.put("orderId", message.getOrderId());
                param.put("amt", amount.substring(amount.indexOf("CNY") + 3, amount.length()));
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "00");
                param.put("retCode", "00");
                param.put("retMsg", "");
                param.put("signData", message.getSignMessage());
                param.put("isFront", String.valueOf(message.isFront()));
                result.setModel("isNotifyCashier", param);
                result.setOrderStatus(true);
                result.setSuccess(true);
            } else {
             // 如果流水号异常，调用流水号任务
                if (message != null && message.getMsgBody().getSysRtnInf().getSysRtnCd() != null
                        && (NuccConstants.NUCC_SYSRTNCD_SERIAL_ERROR
                                .equals(message.getMsgBody().getSysRtnInf().getSysRtnCd()))) {
                	nuccSerialManager.getFlowIdRule();

                }
                param.put("orderId", message.getOrderId());
                param.put("amt", message.getAmount().toString());
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "01");
                param.put("retCode", "01");
                param.put("retMsg",
                        NuccConstants.NUCC_SYSRTNCD_SUCCESS
                                .equals(message.getMsgBody().getSysRtnInf().getSysRtnCd())
                                        ? message.getMsgBody().getBizInf().getBizStsDesc()
                                        : message.getMsgBody().getSysRtnInf().getSysRtnDesc());
                param.put("signData", message.getSignMessage());
                param.put("isFront", String.valueOf(message.isFront()));
                result.setModel("isNotifyCashier", param);
                result.setOrderStatus(false);
                result.setSuccess(true);
            }
        } catch (GopayException e) {
            BankLogUtils.printServiceImplExceptionLog(e);
            result.setResultCode(e.getErrCode());
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6088);
        }
        return result;
    }

    @Override
    public Result verify(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        NuccExpaymentEndRes message = new NuccExpaymentEndRes();
        BeanUtils.copyProperties(baseMsg, message);
        try {
            message = (NuccExpaymentEndRes) nuccExPayManager.payVerify(message);
            result.setModel("res", message);
            result.setDefaultModel(message.isSuccess());
            Map<String, String> param = new HashMap<String, String>();
            if (message.isSuccess()
                    && NuccConstants.NUCC_SYSRTNCD_SUCCESS.equals(message.getMsgBody().getSysRtnInf().getSysRtnCd())
                    && (NuccConstants.NUCC_TRXSTATUSCD_SUCCESS.equals(message.getMsgBody().getBizInf().getTrxStatus())
                            || NuccConstants.NUCC_EXCEPTION_SUCCESS.equals(message.getMsgBody().getBizInf().getTrxStatus()))) {
                param.put("orderId", message.getOrderId());
                String amount = message.getMsgBody().getBizInf().getTrxAmt();
                param.put("amt", amount.substring(amount.indexOf("CNY") + 3, amount.length()));
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "00");
                param.put("retCode", "00");
                param.put("retMsg", "验签成功");
                param.put("signData", message.getSignMessage());
                param.put("isFront", String.valueOf(baseMsg.isFront()));
                result.setModel("isNotifyCashier", param);
                result.setSuccess(true);
                result.setOrderStatus(true);
                // 退款时用到
                baseMsg.setBankReturnOrderId(message.getMsgBody().getBizInf().getDbtrBankId());
            } else {
                // 通知后台地址该订单失败
                param.put("orderId", message.getOrderId());
                param.put("amt", message.getAmount().toString());
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "01");
                param.put("retCode", "01");
                // 记录数据库失败信息 add by zhengxue 20170313
                param.put("retMsg",
                        NuccConstants.NUCC_SYSRTNCD_SUCCESS
                                .equals(message.getMsgBody().getSysRtnInf().getSysRtnCd())
                                        ? message.getMsgBody().getBizInf().getBizStsDesc()
                                        : message.getMsgBody().getSysRtnInf().getSysRtnDesc());
                param.put("signData", message.getSignMessage());
                param.put("isFront", String.valueOf(baseMsg.isFront()));
                result.setModel("isNotifyCashier", param);
                result.setSuccess(true);
                result.setOrderStatus(false);
            }

        } catch (GopayException e) {
            BankLogUtils.printServiceImplExceptionLog(e);
            result.setResultCode(e.getErrCode());
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6064);
        }
        return result;
    }

    @Override
    public Result treatyQuery(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result queryOrder(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        NuccExpayBaseMessage message = new NuccExpayBaseMessage();
        BeanUtils.copyProperties(baseMsg, message);
        try {
            NuccExpayQueryRes res = (NuccExpayQueryRes) nuccExPayManager.queryOrder(message);
            result.setDefaultModel(res);
            result.setSuccess(true);
        } catch (GopayException e) {
            BankLogUtils.printServiceImplExceptionLog(e);
            result.setResultCode(e.getErrCode());
        }
        return result;
    }

    @Override
    public Result queryCvn(ExPayBaseMessage baseMsg) {
        Result result = new Result();
        result.setSuccess(true);
        result.setModel("flag", true);
        result.setModel("isQueryCVN", YeePayConstants.YEEPAY_EXPAY_ISQUERYCVN);
        return result;
    }

    @Override
    public Result queryNeedCert(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }
    
    

    /**
     * 根据卡号和签约银行查询生效签约记录
     * 
     * @param message
     * @return
     */
    public BisBankContractInfo findContractInfo(ExPayBaseMessage message) {
        BisBankContractInfo bisBankContractInfo = new BisBankContractInfo();
        bisBankContractInfo.setBankCode(message.getBank());
        bisBankContractInfo.setCardNo(message.getCardNo());
        bisBankContractInfo.setBankBizProdCode(message.getBankBusProd().value);
        bisBankContractInfo.setIntrfaceChannelCode(message.getBankIntrChann().value);
        return bankContractInfoDAO.getContractInfoByCard(bisBankContractInfo);
    }

    /**
     * 根据签约协议号，银行码，通道，查找签约记录
     * 
     * @param sgnNo
     * @param bankCode
     * @param channel
     * @return
     * @author w_jiqing
     */
    public BisBankContractInfo findContractInfoBySgnNo(String sgnNo, String bankCode, String channel) {
        BisBankContractInfo bisBankContractInfo = new BisBankContractInfo();
        bisBankContractInfo.setBankCode(bankCode);
        bisBankContractInfo.setContractNumber(sgnNo);
        bisBankContractInfo.setIntrfaceChannelCode(channel);
        return bankContractInfoDAO.getContractInfoBySingNo(bisBankContractInfo);

    }

    public void updateContractStateBySingNo(BisBankContractInfo bbci) {
        bankContractInfoDAO.updateContractStateBySingNo(bbci);
    }

    /**
     * 新建鉴权绑卡信息
     * 
     * @param message
     * @param bindCardId
     *            银行返回绑卡ID
     * @return
     */
    public void newContract(ExPayBaseMessage message, String bindCardId) {
        BisBankContractInfo bisBankContractInfo = new BisBankContractInfo();
        bisBankContractInfo.setBankCode(message.getBank());
        bisBankContractInfo.setBankBizProdCode(message.getBankBusProd().value);
        bisBankContractInfo.setIntrfaceChannelCode(message.getBankIntrChann().value);
        bisBankContractInfo.setCardNo(message.getCardNo());
        bisBankContractInfo.setContractState(BankContractConstants.CONTRACT_SUCCESS);
        bisBankContractInfo.setContractNumber(bindCardId);
        String verifyCode = createVerificationCode(message);
        // 保存四要素校验码
        bisBankContractInfo.setVerificationCode(verifyCode);
        bankContractInfoDAO.insertBisBankContractInfo(bisBankContractInfo);
    }

    /**
     * 更新签约记录
     * 
     * @param message
     * @param bindCardId
     *            签约协议号
     */
    public void updateContractInfo(ExPayBaseMessage message, String bindCardId) {
        BisBankContractInfo bisBankContractInfo = new BisBankContractInfo();
        bisBankContractInfo.setContractState(BankContractConstants.CONTRACT_SUCCESS);
        bisBankContractInfo.setCardNo(message.getCardNo());
        bisBankContractInfo.setContractNumber(bindCardId);
        bisBankContractInfo.setBankCode(message.getBank());
        bisBankContractInfo.setIntrfaceChannelCode(message.getBankIntrChann().value);
        String verifyCode = createVerificationCode(message);
        // 保存四要素校验码
        bisBankContractInfo.setVerificationCode(verifyCode);
        bankContractInfoDAO.updateContractInfoAndElements(bisBankContractInfo);
    }

    public void updateContractStatus(ExPayBaseMessage message, String status) {
        BisBankContractInfo bisBankContractInfo = new BisBankContractInfo();
        bisBankContractInfo.setContractState(status);
        bisBankContractInfo.setCardNo(message.getCardNo());
        bisBankContractInfo.setBankCode(message.getBank());
        bisBankContractInfo.setIntrfaceChannelCode(message.getBankIntrChann().value);
        bisBankContractInfo.setBankBizProdCode(message.getBankBusProd().value);
        bankContractInfoDAO.updateContractStateByCardNo(bisBankContractInfo);
    }

    /**
     * 根据用户输入的四要素/六要素创建校验码
     * 
     * @param message
     * @return
     */
    public String createVerificationCode(ExPayBaseMessage message) {
        StringBuffer msg = new StringBuffer();
        // 信用卡 增加CVN2和有效期两要素
        if (BisBankBusinessProd._05.value.equals(message.getBankBusProd().value)) {
            msg.append(message.getCvv2());
            msg.append(message.getAvailableDate());
        }
        msg.append(message.getCardHolder());
        msg.append(message.getCardNo());
        msg.append(message.getIdentityCode());
        msg.append(message.getMediaId());
        return MD5Util.sign(msg.toString());
    }

    public NuccExPayManager getNuccExPayManager() {
        return nuccExPayManager;
    }

    public void setNuccExPayManager(NuccExPayManager nuccExPayManager) {
        this.nuccExPayManager = nuccExPayManager;
    }

    public SmsSupportController getSmsController() {
        return smsController;
    }

    public void setSmsController(SmsSupportController smsController) {
        this.smsController = smsController;
    }

}
